#include "log4cpp/Category.hh"
#include "log4cpp/Appender.hh"
#include "log4cpp/FileAppender.hh"
#include "log4cpp/OstreamAppender.hh"
#include "log4cpp/Layout.hh"
#include "log4cpp/BasicLayout.hh"
#include "log4cpp/Priority.hh"
using namespace log4cpp;

int main(int argc, char** argv) {
    //1.创建目的地对象
    //2.目的地绑定布局
    //3.创建记录器
    //4.记录器设置优先级
    //5.记录器添加目的地
    //6.写入日志

    //基类指针指向派生类对象
	/* Appender * appender1 = new OstreamAppender("console", &std::cout); */
	/* auto appender1 = new OstreamAppender("console", &std::cout); */

    //设置目的地（输出器）
    //第一个参数代表目的地名字，代码仅作指示（随便写）
    //第二个参数是ostream * ,此处传入&cout，将目的地设为了输出到终端
	OstreamAppender * appender1 = new OstreamAppender("console", &std::cout);
    //设置布局（将目的地与日志布局进行了绑定）
    //此处设为了基本布局（不容易观察）
	appender1->setLayout(new BasicLayout());


    //设置目的地
    //FileAppender构造函数的第一个参数代表目的地名字（随便写）
    //第二个参数代表保存日志信息的文件名
	FileAppender * appender2 = new FileAppender("default", "program.log");
	appender2->setLayout(new BasicLayout());

    
    //getRoot创建root节点的Category
    //代码中用root这个引用变量进行了绑定
	Category& root = Category::getRoot();
    //root节点设置优先级（门槛）为WARN级别
    //设置目的地为输出到终端
	root.setPriority(Priority::DEBUG);
	root.addAppender(appender1);

    //getInstance函数创建了root节点的Category对象下一级的叶子结点
    //叶子结点也是Category对象
    //继承了root的优先级和目的地
    //代码中用sub1引用变量绑定了这个叶子结点Category对象
	Category& sub1 = Category::getInstance("sub1");

    //一个Category对象的唯一性由getInstance的参数决定
    //这个Category名字也会体现在日志信息中
    //前面的sub1、sub10代表绑定到这同一个Category对象的
    //不同引用变量，供代码中使用
	Category& sub10 = Category::getInstance("sub1");

	Category& sub2 = Category::getInstance("sub2");
	Category& sub11 = Category::getInstance("sub1.sub11");

    //可以重新设置优先级
    /* sub1.setPriority(Priority::ERROR); */
    //可以不继承root的目的地
    /* sub1.setAdditivity(false); */

    //sub1又添加了一个目的地 —— 保存到文件
	sub1.addAppender(appender2);


	// use of functions for logging messages
	root.error("root error");
	root.info("root info");
	sub1.error("sub1 error");
	sub1.warn("sub1 warn");

	// printf-style for logging variables
	root.warn("%d + %d == %s ?", 1, 1, "two");

	// use of streams for logging messages
	root << Priority::ERROR << "Streamed root error";
	root << Priority::INFO << "Streamed root info";
	sub1 << Priority::ERROR << "Streamed sub1 error";
	sub1 << Priority::WARN << "Streamed sub1 warn";

	// or this way:
	root.errorStream() << "Another streamed error";

	return 0;
}
